/*
 * edulisp_scanner.cpp
 *
 *  Created on: 07.04.2011
 *      Author: xdn
 */

#include "edulisp_scanner.hpp"
//Локальные инклады

enum SSM_State {
    SSMS_S = 1,  // Начальное состояние
    SSMS_L,  // Идентификатор
    SSMS_D,  // Целое число
    SSMS_D2, // Дробная часть числа
    SSMS_CI, // Операторы?
    SSMS_Q,  // Строковая константа
    SSMS_E,
    SSMS_C1, // Строчный комментарий
	SSMS_C2,
	SSMS_C3, // Многострочный комментарий
	SSMS_C4,
	SSMS_C5,
	//
	//
	SSMS_ED, // Конечное состояние
	SSMS_E1,
	SSMS_E2,
	SSMS_E3,
	SSMS_E4,
	SSMS_E5,  // Необрабатываемый символ в коде программы
	SSMS_E6
};
//Состояния конечного автомата сканера


enum SSM_Event { SSME_LETTER, SSME_DIGIT, SSME_DOT, SSME_DECORATION, SSME_EOF,
	SSME_QUOTE, SSME_BACKSLASH, SSME_SEMICOLON, SSME_SLASH, SSME_CHARID,
	SSME_BRACKET_CLOSING, SSME_LINEFEED, SSME_CARRIEGERETURN, SSME_SPACE,
	SSME_SHARP, SSME_OPERATOR, SSME_CHARFUNCTION, SSME_ELSE, SSME_OTHER };
//События конечного автомата сканера

//!Экспериментальный сегмент!
//События высокоуровневого конечного автомата сканер
enum HLSSM_State { HLSSME_NORMAL, HLSSME_DEFUN_NAME, HLSSME_DEFUN_NAME2,
	HLSSME_DEFUN_ARGUMENTS, HLSSME_DEFUN_CODE, HLSSME_LAMBDA_ARGUMENTS, HLSSME_IF,
	HLSSME_IF_EXPR, HLSSME_IF_COND1, HLSSME_IF_COND2 };
//

// Получение идентификатора
static int GetOperatorID(string& Operator)
{
	if (Operator == "(") return SSMO_BRACKET;
	if (Operator == ".") return SSMO_DOT;
	if (Operator == ")") return SSMO_BRACKET_CLOSING;
	return 0;
}

class SSM;
class HLSSM;

//Действие конечного автомата
typedef void (*SSM_Action)(SSM& StateMachine);
typedef void (*HLSSM_Action)(HLSSM& StateMachine);

//typedef SSM_Action* SSM_ActionList;

struct SSM_Transition
{
	int BaseState;
	unsigned int Event;
	int TargetState;
	const SSM_Action *ActionList;
};

template <typename EventType> struct HLSSM_Transition_Template
{
	int BaseState;
	EventType Event;
	int TargetState;
	const HLSSM_Action *ActionList;
};

typedef SSM_Transition SSM_Transition;

//!Экспериментальный сегмент!
typedef HLSSM_Transition_Template<int> HLSSM_Transition_Operator;
typedef HLSSM_Transition_Template<string> HLSSM_Transition_Ident;

typedef deque<unsigned int> InsertionList;

struct SSM_InternalState
{
	LexemeList *LL;
	unsigned int BracketCounter;
	int FunctionID;
	int HLSSM_State;
	InsertionList *InsertionList_;
};

typedef stack<SSM_InternalState> HLSSM_Directions;

NameTable_Entry *AddIdentToNT(NameTable& NT, string *Name, int Owner = -1);

void DeleteLexeme(HLSSM& HLSSM_);
void AddOperator(HLSSM& HLSSM_);
void SelectTarget(HLSSM& HLSSM_);
void PassToUpperSM(HLSSM& HLSSM_);
void PassToUpperSMNoAdd(HLSSM& HLSSM_);
void PushInternalState(HLSSM& HLSSM_);
void AddArgument(HLSSM& HLSSM_);
void AddFunction(HLSSM& HLSSM_);
void AddNonameFunction(HLSSM& HLSSM_);
void IncBracketCounter(HLSSM& HLSSM_);
void DecBracketCounter(HLSSM& HLSSM_);
void AddLastNTEToLexemeList(HLSSM& HLSSM_);
void AddGoto(HLSSM& HLSSM_);
void AddIfGoto(HLSSM& HLSSM_);
void RollbackLexeme(HLSSM& HLSSM_);
void InsertAddress(HLSSM& HLSSM_);

enum HLSSM_Result { HLSSMR_OK, HLSSMR_PASS, HLSSMR_NOADD };

class HLSSM
{
//Функции-друзья
	friend void DeleteLexeme(HLSSM& HLSSM_);
	friend void AddOperator(HLSSM& HLSSM_);
	friend void SelectTarget(HLSSM& HLSSM_);
	friend void PassToUpperSM(HLSSM& HLSSM_);
	friend void PassToUpperSMNoAdd(HLSSM& HLSSM_);
	friend void PushInternalState(HLSSM& HLSSM_);
	friend void AddArgument(HLSSM& HLSSM_);
	friend void AddFunction(HLSSM& HLSSM_);
	friend void AddNonameFunction(HLSSM& HLSSM_);
	friend void IncBracketCounter(HLSSM& HLSSM_);
	friend void DecBracketCounter(HLSSM& HLSSM_);
	friend void AddLastNTEToLexemeList(HLSSM& HLSSM_);
	friend void AddGoto(HLSSM& HLSSM_);
	friend void AddIfGoto(HLSSM& HLSSM_);
	friend void RollbackLexeme(HLSSM& HLSSM_);
	friend void InsertAddress(HLSSM& HLSSM_);
//
private:
	int Q;
	SSM& Owner;
	const HLSSM_Transition_Operator *OTT;
	unsigned int OTT_Length;
	const HLSSM_Transition_Ident *ITT;
	unsigned int ITT_Length;
	HLSSM_Directions Directions;
	LexemeList *Direction;
	NameTable_Entry *Target;
	HLSSM_Result Result;
	unsigned int BracketCounter;
	int LastFunctionID;
	InsertionList *InsertionList_;
public:
	HLSSM(int StartState, SSM& Owner_,
			const HLSSM_Transition_Operator *OTT_ = NULL,
			unsigned int OTT_Length_ = 0,
			const HLSSM_Transition_Ident *ITT_ = NULL,
			unsigned int ITT_Length_ = 0);
	~HLSSM();
	HLSSM_Result Do(int Event);
	HLSSM_Result Do(string Event);
protected:
};
//

class SSM
{
	friend class HLSSM;
	friend void AddOperator(HLSSM& HLSSM_);
	friend void SelectTarget(HLSSM& HLSSM_);
	friend void PushInternalState(HLSSM& HLSSM_);
	friend void AddArgument(HLSSM& HLSSM_);
	friend void AddFunction(HLSSM& HLSSM_);
	friend void AddNonameFunction(HLSSM& HLSSM_);
	friend void DecBracketCounter(HLSSM& HLSSM_);
	friend void AddLastNTEToLexemeList(HLSSM& HLSSM_);
	friend void AddGoto(HLSSM& HLSSM_);
	friend void AddIfGoto(HLSSM& HLSSM_);
	friend void RollbackLexeme(HLSSM& HLSSM_);
	friend void InsertAddress(HLSSM& HLSSM_);
private:
	int Q;     // текущее состояние
	const int EndState;
	const int *ErrorStates;
	unsigned int CurrentCharIndex;
	string Buf;
	//stringstream Buf;
	const SSM_Transition *P;
	const unsigned int P_length;
	LexemeList *LL;
	NameTable *NT;
	const int *Vocab;
	unsigned char CurrentChar;
	int FunctionID;
	HLSSM HLSSM_;
	LocalVariables *LocalVariables_;
public:
	SSM(int StartState, const SSM_Transition *TransitionTable,
			unsigned int TransitionTableLength, int *Vocab,
			int EndState_, const int *ErrorStates_, LexemeList& lLexemeList,
			NameTable& mNameTable, int HLSSM_StartState,
			const HLSSM_Transition_Operator *OTT_ = NULL,
			unsigned int OTT_Length_ = 0,
			const HLSSM_Transition_Ident *ITT_ = NULL,
			unsigned int ITT_Length_ = 0);
	void Do(int Event);
	int Finished();
	void RollbackChar();
	unsigned int GetCurrentCharIndex();
	int GetCurrentState();
	void AddCharToBuf();
	void AddIdent();
	void ClearBuffer();
	void AddInteger();
	void AddFloat();
	void AddString();
	void AddFunction();
	string ParseEscape(string& sText);
	void AddOperator();
	int Parse(string& Text);
protected:
};

SSM::SSM(int StartState, const SSM_Transition *TransitionTable,
		const unsigned int TransitionTableLength, int *Vocab_,
		int EndState_, const int *ErrorStates_, LexemeList& lLexemeList,
		NameTable& mNameTable, int HLSSM_StartState,
		const HLSSM_Transition_Operator *OTT_, unsigned int OTT_Length_,
		const HLSSM_Transition_Ident *ITT_, unsigned int ITT_Length_)
	: Q(StartState), EndState(EndState_), ErrorStates(ErrorStates_),
	  CurrentCharIndex(0), P(TransitionTable), P_length(TransitionTableLength),
	  LL(&lLexemeList), NT(&mNameTable), Vocab(Vocab_), FunctionID(-1),
	  HLSSM_(HLSSM_StartState, *this, OTT_, OTT_Length_,  ITT_, ITT_Length_),
	  LocalVariables_(NULL)
{
	lLexemeList.clear();
	mNameTable.clear();
	//mNameTable.push_back(Buf);
}

void SSM::Do(int Event)
{
	const SSM_Transition *T = P;
	const SSM_Transition *ST = NULL;
	for (unsigned int i = 0; i < P_length; i++, T++)
	{
		if (T->BaseState == Q)
		{
			if ((T->Event == SSME_ELSE) || (T->Event == Event))
				ST = T;
			if (T->Event == Event)
				break;
		}
	}
	if (ST)
	{
		const SSM_Action *Action = ST->ActionList;
		if (Action)
			while(*Action)
				(*Action++)(*this);

		Q = ST->TargetState;
	}

	CurrentCharIndex++;
}

int SSM::Parse(string& Text)
{
	int Result;
	while(!(Result = Finished()))
	{
		if (CurrentCharIndex > Text.length())
			return SEC_INTERNAL;

		CurrentChar = Text[CurrentCharIndex];
		Do(Vocab[CurrentChar]);
	}

	return Result;
}

int SSM::Finished()
{
	if (Q == EndState)
		return 1;
	for(const int *i = ErrorStates; *i; i++)
		if (Q == *i)
			return 2;

	return 0;
}

void SSM::RollbackChar()
{
	CurrentCharIndex--;
}

unsigned int SSM::GetCurrentCharIndex()
{
	return CurrentCharIndex;
}

int SSM::GetCurrentState()
{
	return Q;
}

void SSM::ClearBuffer()
{
	Buf.clear();
}

void SSM::AddCharToBuf()
{
	Buf += CurrentChar;
}

void SSM::AddIdent()
{
	// -- неключевое слово --
	int index;

	HLSSM_Result HLResult = HLSSM_.Do(Buf);
	if ((HLResult == HLSSMR_PASS) || (HLResult == HLSSMR_NOADD))
	{
		if ((index = NT->NameIndex(Buf, FunctionID)) == -1)
		{
			NT->push_back(new NameTable_Entry(&Buf, FunctionID));
			index = NT->size() - 1;

			if (LocalVariables_ &&
					(LocalVariables_->find(index) == LocalVariables_->end()))
				LocalVariables_->insert(LocalVariable(index,
						new NameTable_Entry(*(NT->at(index)))));
		}
	}
	if (HLResult == HLSSMR_PASS)
		LL->push_back(index);
	ClearBuffer();
}

void SSM::AddInteger()
{
	int index;
	if ((index = NT->NameIndex(Buf)) == -1)
	{
		int ints;
		istringstream is(Buf);
		is >> ints;
		NT->push_back(new NameTable_Entry(&Buf, LT_CONST, ints));
		index = NT->size() - 1;
	}
	LL->push_back(index);
	ClearBuffer();
}

// !!! При высокой точности возникает ошибка сегментации !!!
void SSM::AddFloat()
{
	int index;
	if ((index = NT->NameIndex(Buf)) == -1)
	{
		double flts;
		istringstream is(Buf);
		is >> flts;
		NT->push_back(new NameTable_Entry(&Buf, LT_CONST, flts));
		index = NT->size() - 1;
	}
	LL->push_back(index);
	ClearBuffer();
}

void SSM::AddString()
{
	int index;
	string ParsedValue = ParseEscape(Buf);
	if ((index = NT->StringValueIndex(ParsedValue)) == -1)
	{
		NT->push_back(new NameTable_Entry(LT_CONST, ParsedValue));
		index = NT->size() - 1;
	}
	LL->push_back(index);
	ClearBuffer();
}

void SSM::AddOperator()
{
    //LL->push_back("OPERATOR=" + Buf);
	int Operator = GetOperatorID(Buf);
	if (HLSSM_.Do(Operator) == HLSSMR_PASS)
		LL->push_back(-Operator);

    ClearBuffer();
}

string SSM::ParseEscape(string& sText)
{
	string Buf;
	bool EscapeFlag = false;
	for(unsigned int i = 0; i < sText.length(); i++)
	{
		if (!EscapeFlag)
		{
			if (sText[i] == '\\')
				EscapeFlag = true;
			else
				Buf += sText[i];
		}
		else
		{
			switch(sText[i])
			{
			case 'n':
				Buf += '\n';
				break;
			case 'r':
				Buf += '\r';
				break;
			case 't':
				Buf += '\t';
				break;
			default:
				Buf += sText[i];
			}

			EscapeFlag = false;
		}
	}

	return Buf;
}

//--------- Transition actions -----------------//

void ClearBuffer(SSM& StateMachine)
{
	StateMachine.ClearBuffer();
}

void RollbackChar(SSM& StateMachine)
{
	StateMachine.RollbackChar();
}

void AddCharToBuf(SSM& StateMachine)
{
	StateMachine.AddCharToBuf();
}

void AddIdent(SSM& StateMachine)
{
	StateMachine.AddIdent();
}

void AddInteger(SSM& StateMachine)
{
	StateMachine.AddInteger();
}

void AddOperator(SSM& StateMachine)
{
    StateMachine.AddOperator();
}

void AddFloat(SSM& StateMachine)
{
	StateMachine.AddFloat();
}

void AddString(SSM& StateMachine)
{
	StateMachine.AddString();
}

static const SSM_Action AL_AddCharToBuf[] = { &AddCharToBuf, NULL };
static const SSM_Action AL_AddIdent[] = { &AddIdent, NULL };
static const SSM_Action AL_AddIdentAndRollback[] = { &AddIdent, &RollbackChar,
		NULL };
static const SSM_Action AL_AddInteger[] = { &AddInteger, NULL };
static const SSM_Action AL_AddIntegerAndRollback[] = { &AddInteger, &RollbackChar,
		NULL };
static const SSM_Action AL_AddFloat[] = { &AddFloat, NULL };
static const SSM_Action AL_AddFloatAndRollback[] = { &AddFloat, &RollbackChar,
		NULL };
static const SSM_Action AL_AddString[] = { &AddString, NULL };

static const SSM_Action AL_AddOperator[] = { &AddCharToBuf, &AddOperator, NULL };
static const SSM_Action AL_RollbackChar[] = { &RollbackChar, NULL };

static const SSM_Action AL_ClearBuffer[] = { &ClearBuffer, NULL };

static const SSM_Transition TT_EduLisp[] =
{
		//L
		{ SSMS_S, SSME_LETTER, SSMS_L, AL_AddCharToBuf },
		//{ SSMS_S, SSME_CHARFUNCTION, SSMS_L, AL_AddCharToBuf },
		{ SSMS_L, SSME_DIGIT, SSMS_L, AL_AddCharToBuf },
		{ SSMS_L, SSME_LETTER, SSMS_L, AL_AddCharToBuf },
		{ SSMS_L, SSME_LINEFEED, SSMS_S, AL_AddIdent },
		{ SSMS_L, SSME_DECORATION, SSMS_S, AL_AddIdent },
		{ SSMS_L, SSME_CARRIEGERETURN, SSMS_S, AL_AddIdent },
		{ SSMS_L, SSME_SPACE, SSMS_S, AL_AddIdent },
		{ SSMS_L, SSME_BRACKET_CLOSING, SSMS_S, AL_AddIdentAndRollback },
		//{ SSMS_L, SSME_CHARFUNCTION, SSMS_E6, NULL },
		{ SSMS_L, SSME_EOF, SSMS_S, AL_AddIdentAndRollback },
		{ SSMS_L, SSME_ELSE, SSMS_E1, NULL },
		//END L

		//D
		{ SSMS_S, SSME_DIGIT, SSMS_D, AL_AddCharToBuf },
		{ SSMS_D, SSME_DIGIT, SSMS_D, AL_AddCharToBuf },
		{ SSMS_D, SSME_LINEFEED, SSMS_S, AL_AddInteger },
		{ SSMS_D, SSME_CARRIEGERETURN, SSMS_S, AL_AddInteger },
		{ SSMS_D, SSME_SPACE, SSMS_S, AL_AddInteger },
		{ SSMS_D, SSME_BRACKET_CLOSING, SSMS_S, AL_AddIntegerAndRollback },
		{ SSMS_D, SSME_EOF, SSMS_S, AL_AddIntegerAndRollback },
		{ SSMS_D, SSME_SEMICOLON, SSMS_S, AL_AddIntegerAndRollback },
		{ SSMS_D, SSME_DOT, SSMS_D2, AL_AddCharToBuf },
		{ SSMS_D, SSME_SLASH, SSMS_S, AL_AddIntegerAndRollback },
		{ SSMS_D, SSME_ELSE, SSMS_E2, NULL },
		//END D


		//D2
		{ SSMS_D2, SSME_DIGIT, SSMS_D2, AL_AddCharToBuf },
		{ SSMS_D2, SSME_LINEFEED, SSMS_S, AL_AddFloat },
		{ SSMS_D2, SSME_CARRIEGERETURN, SSMS_S, AL_AddFloat },
		{ SSMS_D2, SSME_SPACE, SSMS_S, AL_AddFloat },
		{ SSMS_D2, SSME_BRACKET_CLOSING, SSMS_S, AL_AddFloatAndRollback },
		{ SSMS_D2, SSME_EOF, SSMS_S, AL_AddFloatAndRollback },
		{ SSMS_D2, SSME_SEMICOLON, SSMS_S, AL_AddFloatAndRollback },
		{ SSMS_D2, SSME_SLASH, SSMS_S, AL_AddFloatAndRollback },
		{ SSMS_D2, SSME_ELSE, SSMS_E2, NULL },
		//END D2

		//Q
		{ SSMS_S, SSME_QUOTE, SSMS_Q, NULL },
		{ SSMS_Q, SSME_EOF, SSMS_E3, NULL },
		{ SSMS_Q, SSME_QUOTE, SSMS_S, AL_AddString },
		{ SSMS_Q, SSME_SLASH, SSMS_E, AL_AddCharToBuf },
		{ SSMS_Q, SSME_ELSE, SSMS_Q, AL_AddCharToBuf },
		//END Q

		//E
		{ SSMS_E, SSME_ELSE, SSMS_Q, AL_AddCharToBuf },
		//END E

		//C1
		{ SSMS_S, SSME_SEMICOLON, SSMS_C1, NULL },
        { SSMS_C1, SSME_LINEFEED, SSMS_C2, NULL },
        { SSMS_C1, SSME_EOF, SSMS_S, AL_RollbackChar },
        //END C1

        //C2
        { SSMS_C2, SSME_CARRIEGERETURN, SSMS_S, NULL },
		{ SSMS_C2, SSME_ELSE, SSMS_C1, NULL },
		//END C1

		//C3
        { SSMS_S, SSME_SLASH, SSMS_C3, AL_AddCharToBuf },
        { SSMS_C3, SSME_SHARP, SSMS_C4, AL_ClearBuffer },
        { SSMS_C3, SSME_SPACE, SSMS_S, AL_AddIdent },
        { SSMS_C3, SSME_EOF, SSMS_S, AL_AddIdent },
        //{ SSMS_C3, SSME_ELSE, SSMS_E6, NULL },
        { SSMS_C3, SSME_ELSE, SSMS_L, AL_RollbackChar },
        //END C3

        //C4
        { SSMS_C4, SSME_SHARP, SSMS_C5, NULL },
        { SSMS_C4, SSME_EOF, SSMS_E4, NULL },
        //END C4

        //END C5
        { SSMS_C5, SSME_SLASH, SSMS_S, NULL },
		{ SSMS_C5, SSME_ELSE, SSMS_C4, NULL },
		//END C5

		//S
		{ SSMS_S, SSME_OPERATOR, SSMS_S, AL_AddOperator },
		{ SSMS_S, SSME_BRACKET_CLOSING, SSMS_S, AL_AddOperator },
		{ SSMS_S, SSME_DOT, SSMS_S, AL_AddOperator },
		{ SSMS_S, SSME_OTHER, SSMS_E5, NULL },
		//END S

		{ SSMS_S, SSME_EOF, SSMS_ED, NULL }
};

static const int ErrorStates[] = { SSMS_E1, SSMS_E2, SSMS_E3, SSMS_E4, SSMS_E5,
		SSMS_E6, NULL };

//Экспериментальная секция
static const HLSSM_Action HL_AL_DeleteLexeme[] =
	{ DeleteLexeme, NULL };

static const HLSSM_Action HL_AL_Pass[] =
	{ PassToUpperSM, NULL };

static const HLSSM_Action HL_AL_PassNoAdd[] =
	{ PassToUpperSMNoAdd, NULL };

static const HLSSM_Action HL_AL_SelectIdent[] =
	{ SelectTarget, NULL };

static const HLSSM_Action HL_AL_DoubleRollback[] =
	{ DeleteLexeme, DeleteLexeme, NULL };

static const HLSSM_Action HL_AL_AddArgument[] =
	{ AddArgument, NULL };

static const HLSSM_Action HL_AL_PushInternalState[] =
	{ PushInternalState, NULL };

static const HLSSM_Action HL_AL_IncBracketCounterAndPass[] =
	{ PassToUpperSM, IncBracketCounter, NULL };

static const HLSSM_Action HL_AL_DecBracketCounterAndPass[] =
	{ PassToUpperSM, DecBracketCounter, NULL };

static const HLSSM_Action HL_AL_AddFunction[] =
	{ AddFunction, NULL };

static const HLSSM_Action HL_AL_Lambda[] =
	{ AddNonameFunction, SelectTarget, AddLastNTEToLexemeList, NULL };

static const HLSSM_Action HL_AL_If[] =
	{ DeleteLexeme, PushInternalState, NULL };

static const HLSSM_Action HL_AL_IfCond1[] =
	{ AddIfGoto, PushInternalState, IncBracketCounter, PassToUpperSM, NULL };

static const HLSSM_Action HL_AL_IfCond2[] =
	{ AddGoto, InsertAddress, PushInternalState, IncBracketCounter, PassToUpperSM,
			NULL };

static const HLSSM_Action HL_AL_IncBracketCounter[] =
	{ IncBracketCounter, NULL };

static const HLSSM_Action HL_AL_InsertAddress[] =
	{ InsertAddress, NULL };

static const HLSSM_Action HL_AL_InsertAddressAndDec[] =
	{ InsertAddress, DecBracketCounter, NULL };

static const HLSSM_Transition_Operator OTT_EduLisp[] =
{
		{ HLSSME_DEFUN_NAME2, SSMO_BRACKET, HLSSME_DEFUN_ARGUMENTS,
				HL_AL_SelectIdent },
		{ HLSSME_DEFUN_ARGUMENTS, SSMO_BRACKET_CLOSING, HLSSME_DEFUN_CODE,
				HL_AL_PushInternalState },
		//{ HLSSME_DEFUN_ARGUMENTS, SSMO_BRACKET, HLSSME_DEFUN_ARGUMENTS,
				//NULL },
		{ HLSSME_DEFUN_CODE, SSMO_BRACKET_CLOSING, HLSSME_NORMAL,
				NULL },
		{ HLSSME_DEFUN_ARGUMENTS, SSMO_BRACKET, HLSSME_DEFUN_ARGUMENTS,
				HL_AL_PushInternalState },
		{ HLSSME_LAMBDA_ARGUMENTS, SSMO_BRACKET_CLOSING, HLSSME_NORMAL,
				HL_AL_PushInternalState },
		{ HLSSME_LAMBDA_ARGUMENTS, SSMO_BRACKET, HLSSME_LAMBDA_ARGUMENTS,
				NULL },
		{ HLSSME_NORMAL, SSMO_BRACKET, HLSSME_NORMAL,
				HL_AL_IncBracketCounterAndPass },
		{ HLSSME_NORMAL, SSMO_BRACKET_CLOSING, HLSSME_NORMAL,
				HL_AL_DecBracketCounterAndPass },

		//{ HLSSME_IF, SSMO_BRACKET, HLSSME_IF_EXPR, HL_AL_If },
		//{ HLSSME_IF_EXPR, SSMO_BRACKET_CLOSING, HLSSME_IF_EXPR, NULL },
		{ HLSSME_IF_EXPR, SSMO_BRACKET, HLSSME_IF_COND1, HL_AL_IfCond1 },
		{ HLSSME_IF_COND1, SSMO_BRACKET_CLOSING, HLSSME_NORMAL,
				HL_AL_InsertAddressAndDec },
		{ HLSSME_IF_COND1, SSMO_BRACKET, HLSSME_IF_COND2, HL_AL_IfCond2 },
		{ HLSSME_IF_COND2, SSMO_BRACKET, HLSSME_IF_COND2, NULL },
		{ HLSSME_IF_COND2, SSMO_BRACKET_CLOSING, HLSSME_NORMAL,
				HL_AL_InsertAddressAndDec },

		{ HLSSME_NORMAL, 0, HLSSME_NORMAL, HL_AL_Pass }
};

static const HLSSM_Transition_Ident ITT_EduLisp[] =
{
		{ HLSSME_NORMAL, "defun", HLSSME_DEFUN_NAME,
				HL_AL_DeleteLexeme },
		{ HLSSME_DEFUN_NAME, "", HLSSME_DEFUN_NAME2, HL_AL_AddFunction },
		{ HLSSME_DEFUN_ARGUMENTS, "", HLSSME_DEFUN_ARGUMENTS, HL_AL_AddArgument },
		{ HLSSME_LAMBDA_ARGUMENTS, "", HLSSME_LAMBDA_ARGUMENTS, HL_AL_AddArgument },

		{ HLSSME_NORMAL, "lambda", HLSSME_LAMBDA_ARGUMENTS,
						HL_AL_Lambda },
		{ HLSSME_NORMAL, "if", HLSSME_IF_EXPR, HL_AL_If },


		{ HLSSME_NORMAL, "", HLSSME_NORMAL, HL_AL_Pass }
};
//

int Scan(string& sText, LexemeList& lLexemeList, NameTable& mNameTable,
		TextFormat eTextFormat)
{
    //SM_Populate();
	int Vocablurary[sizeof(char) * 255];
	//memset(Vocablurary, SSME_OTHER, sizeof(Vocablurary));
	for(unsigned int i = 0; i < sizeof(char) * 255; i++)
		Vocablurary[i] = SSME_OTHER;
	Vocablurary['+'] = Vocablurary['-'] = Vocablurary['*'] = Vocablurary['='] =
			//Vocablurary['!'] = Vocablurary['%'] = SSME_CHARFUNCTION;
			Vocablurary['!'] = Vocablurary['%'] = Vocablurary['_'] = SSME_LETTER;
	Vocablurary['\0'] = SSME_EOF;
	Vocablurary[')'] = SSME_BRACKET_CLOSING;
	Vocablurary['\t'] = SSME_DECORATION;
	Vocablurary[' '] = SSME_SPACE;
	Vocablurary['\n'] = SSME_LINEFEED;
	Vocablurary['\r'] = SSME_CARRIEGERETURN;
	Vocablurary['.'] = SSME_DOT;
	Vocablurary['\"'] = SSME_QUOTE;
	Vocablurary['\\'] = SSME_SLASH;
	Vocablurary[';'] = SSME_SEMICOLON;
	Vocablurary['/'] = SSME_SLASH;
	Vocablurary['#'] = SSME_SHARP;
	Vocablurary['('] = SSME_OPERATOR;
	for(unsigned int i = 'A'; i <= 'Z'; i++)
		Vocablurary[i] = SSME_LETTER;
	for(unsigned int i = 'a'; i <= 'z'; i++)
		Vocablurary[i] = SSME_LETTER;
	Vocablurary['_'] = SSME_LETTER;
	for(unsigned int i = '0'; i <= '9'; i++)
		Vocablurary[i] = SSME_DIGIT;

	//HLSSM_TransitionTable_Ident ITT_EduLisp;
	//ITT_EduLisp.push_back(new HLSSM_Transition_Ident(HLSSME_NORMAL, "defun",
			//HLSSME_DEFUN_ARGUMENTS, NULL));


	SSM Scanner(SSMS_S, TT_EduLisp, sizeof(TT_EduLisp) / sizeof(SSM_Transition),
			Vocablurary, SSMS_ED, ErrorStates, lLexemeList, mNameTable,
			HLSSME_NORMAL, OTT_EduLisp,
			sizeof(OTT_EduLisp) / sizeof(HLSSM_Transition_Operator),
			ITT_EduLisp, sizeof(ITT_EduLisp) / sizeof(HLSSM_Transition_Ident));
	//Конечный автомат сканера

	return Scanner.Parse(sText);
}

//!Экспериментальная секция!
HLSSM::HLSSM(int StartState, SSM& Owner_, const HLSSM_Transition_Operator *OTT_,
		unsigned int OTT_Length_, const HLSSM_Transition_Ident *ITT_,
		unsigned int ITT_Length_)
	:Q(StartState), Owner(Owner_), OTT(OTT_), OTT_Length(OTT_Length_), ITT(ITT_),
	ITT_Length(ITT_Length_), Direction(Owner.LL), Target(NULL),
	Result(HLSSMR_OK), BracketCounter(0), LastFunctionID(-1),
	InsertionList_(new InsertionList()) { }

HLSSM::~HLSSM()
{
	while(!Directions.empty())
	{
		delete Directions.top().InsertionList_;
		Directions.pop();
	}

	delete InsertionList_;
}

HLSSM_Result HLSSM::Do(int Event)
{
	Result = HLSSMR_OK;
	const HLSSM_Transition_Operator *T = OTT;
	const HLSSM_Transition_Operator *ST = NULL;
	for(unsigned int i = 0; i < OTT_Length; i++, T++)
	{
		if (T->BaseState == Q)
		{
			if ((T->Event <= 0) || (T->Event == Event))
				ST = T;
			if (T->Event == Event)
				break;
		}
	}
	if (ST)
	{
		Q = ST->TargetState;

		const HLSSM_Action *Action = ST->ActionList;
		if (Action)
			while(*Action)
				(*Action++)(*this);
	}

	return Result;
}

HLSSM_Result HLSSM::Do(string Event)
{
	Result = HLSSMR_OK;
	const HLSSM_Transition_Ident *T = ITT;
	const HLSSM_Transition_Ident *ST = NULL;
	for (unsigned int i = 0; i < ITT_Length;
			i++, T++)
	{
		if (T->BaseState == Q)
		{
			if ((T->Event.empty()) || (T->Event == Event))
				ST = T;
			if (T->Event == Event)
				break;
		}
	}
	if (ST)
	{
		Q = ST->TargetState;

		const HLSSM_Action *Action = ST->ActionList;
		if (Action)
			while(*Action)
				(*Action++)(*this);
	}

	return Result;
}

void DeleteLexeme(HLSSM& HLSSM_)
{
	if (!HLSSM_.Direction->empty())
		HLSSM_.Direction->pop_back();
}

void AddOperator(HLSSM& HLSSM_)
{
	HLSSM_.Direction->push_back(-GetOperatorID(HLSSM_.Owner.Buf));
}

void SelectTarget(HLSSM& HLSSM_)
{
	HLSSM_.Target = HLSSM_.Owner.NT->back();
}

void PassToUpperSM(HLSSM& HLSSM_)
{
	HLSSM_.Result = HLSSMR_PASS;
}

void PassToUpperSMNoAdd(HLSSM& HLSSM_)
{
	HLSSM_.Result = HLSSMR_NOADD;
}

void PushInternalState(HLSSM& HLSSM_)
{
	SSM_InternalState SSM_IS = { HLSSM_.Owner.LL, HLSSM_.BracketCounter,
		HLSSM_.Owner.FunctionID, HLSSM_.Q,
		HLSSM_.InsertionList_ };
	//SSM_IS.InsertionList_ = HLSSM_.InsertionList_;
	HLSSM_.Directions.push(SSM_IS);

	FunctionDescriptor *FD;
	if (HLSSM_.Target)
	{
		FD = HLSSM_.Target->GetFunctionDescriptor();
		HLSSM_.Direction = HLSSM_.Owner.LL = &(FD->GetLexemeList());
		HLSSM_.Target = NULL;
	}
	HLSSM_.BracketCounter = 0;
	HLSSM_.Owner.FunctionID = HLSSM_.LastFunctionID;
	HLSSM_.Owner.LocalVariables_ = (HLSSM_.Target) ? &FD->GetLocalVariables() : NULL;
	HLSSM_.Q = HLSSME_NORMAL;
	/*cout << HLSSM_.InsertionList_.size() << endl;
	cout << "Push:" << endl;
	for (int i = 0; i < HLSSM_.InsertionList_.size(); i++)
		cout << HLSSM_.InsertionList_[i] << ' ';
	cout << endl;*/
	HLSSM_.InsertionList_ = new InsertionList();

	clog << "New context created" << endl;
}

void AddArgument(HLSSM& HLSSM_)
{
	FunctionDescriptor *FD = HLSSM_.Target->GetFunctionDescriptor();
	ArgumentDescriptor *AD = FD->GetArgumentList();
	LocalVariables& LV = FD->GetLocalVariables();
	if (!AD)
		AD = FD->CreateArgumentList();

	NameTable_Entry *NTE = AddIdentToNT(*(HLSSM_.Owner.NT), &HLSSM_.Owner.Buf,
			HLSSM_.LastFunctionID);
	int index;
	AD->push_back((index = HLSSM_.Owner.NT->size() - 1));

	if (LV.find(index) == LV.end())
		LV.insert(LocalVariable(index,
				new NameTable_Entry(*NTE)));
}

NameTable_Entry *AddIdentToNT(NameTable& NT, string *Name, int Owner)
{
	NameTable_Entry *NTE;
	if (!Name || (NT.NameIndex(*Name, Owner) == -1))
	{
		NT.push_back((NTE = new NameTable_Entry(Name, Owner)));
	}
	return NTE;
}

void AddFunction(HLSSM& HLSSM_)
{
	AddIdentToNT(*(HLSSM_.Owner.NT), &HLSSM_.Owner.Buf, HLSSM_.Owner.FunctionID)->
			CreateFunctionDescriptor();
	HLSSM_.LastFunctionID = HLSSM_.Owner.NT->size() - 1;
}

void AddNonameFunction(HLSSM& HLSSM_)
{
	AddIdentToNT(*(HLSSM_.Owner.NT), NULL, HLSSM_.Owner.FunctionID)->
			CreateFunctionDescriptor();
	HLSSM_.LastFunctionID = HLSSM_.Owner.NT->size() - 1;
}

void IncBracketCounter(HLSSM& HLSSM_)
{
	++HLSSM_.BracketCounter;
	//HLSSM_.Result = HLSSMR_PASS;
}

void DecBracketCounter(HLSSM& HLSSM_)
{
	//HLSSM_.Result = HLSSMR_PASS;
	if (HLSSM_.BracketCounter)
	{
		--HLSSM_.BracketCounter;

		if (!HLSSM_.BracketCounter && !HLSSM_.Directions.empty())
		{
			HLSSM_.Owner.LL->push_back(-SSMO_BRACKET_CLOSING);
			HLSSM_.Result = HLSSMR_OK;

			SSM_InternalState& SSM_IS = HLSSM_.Directions.top();
			HLSSM_.Directions.pop();

			HLSSM_.Direction = HLSSM_.Owner.LL = SSM_IS.LL;
			HLSSM_.BracketCounter = SSM_IS.BracketCounter;
			HLSSM_.Owner.FunctionID = SSM_IS.FunctionID;

			if (HLSSM_.Owner.FunctionID == -1)
				HLSSM_.Owner.LocalVariables_ = NULL;
			else
			{
				FunctionDescriptor *FD = HLSSM_.Owner.NT
						->at(HLSSM_.Owner.FunctionID)->GetFunctionDescriptor();
				HLSSM_.Owner.LocalVariables_ = &FD->GetLocalVariables();
			}

			HLSSM_.Q = SSM_IS.HLSSM_State;
			delete HLSSM_.InsertionList_;
			HLSSM_.InsertionList_ = SSM_IS.InsertionList_;

			//HLSSM_.InsertionList_ = SSM_IS.InsertionList_;

			/*cout << HLSSM_.InsertionList_.size() << endl;
			cout << "Pop:" << endl;
			for (int i = 0; i < HLSSM_.InsertionList_.size(); i++)
				cout << HLSSM_.InsertionList_[i] << ' ';
			cout << endl;*/
			clog << "Context popped" << endl;
		}
	}
}

void AddLastNTEToLexemeList(HLSSM& HLSSM_)
{
	HLSSM_.Owner.LL->push_back(HLSSM_.Owner.NT->size() - 1);
}

void AddGoto(HLSSM& HLSSM_)
{
	HLSSM_.Owner.LL->push_back(-SSMO_GOTO);
	HLSSM_.InsertionList_->push_back(HLSSM_.Owner.LL->size());
	HLSSM_.Owner.LL->push_back(0);
}

void AddIfGoto(HLSSM& HLSSM_)
{
	HLSSM_.Owner.LL->push_back(-SSMO_IFGOTO);
	HLSSM_.InsertionList_->push_back(HLSSM_.Owner.LL->size());
	HLSSM_.Owner.LL->push_back(1);
}

void RollbackLexeme(HLSSM& HLSSM_)
{
	--HLSSM_.Owner.CurrentCharIndex;
}

void InsertAddress(HLSSM& HLSSM_)
{
	unsigned int AddressToInsert = HLSSM_.InsertionList_->front();
	HLSSM_.InsertionList_->pop_front();
	HLSSM_.Owner.LL->at(AddressToInsert) = HLSSM_.Owner.LL->size()
			- AddressToInsert;
}
//
